package com.lxr.postdata.common;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.squareup.okhttp.OkHttpClient;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


public class WriteHandlingWebViewClient extends WebViewClient {

    private final String MARKER = "AJAXINTERCEPT";

    /**
     * 请求参数Map集
     */
    private Map<String, String> ajaxRequestContents = new HashMap<>();

    public WriteHandlingWebViewClient(WebView webView) {
        AjaxInterceptJavascriptInterface ajaxInterface = new AjaxInterceptJavascriptInterface(this);
        webView.addJavascriptInterface(ajaxInterface, "interception");
    }

    public WebResourceResponse shouldInterceptRequest(final WebView view, WriteHandlingWebResourceRequest request) throws IOException {

        okhttp3.OkHttpClient httpClient = new okhttp3.OkHttpClient();
        RequestBody body = null;
        if ("POST".equals(request.getMethod())) {
            body = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), request.getAjaxData());
        }

        Request.Builder builder = new Request.Builder()
                .method(request.getMethod(), body)
                .url(request.getUrl().toString())
                .addHeader("Moon-Client", "Moon Electron v1.0_beta");

        Set<String> keySet = request.getRequestHeaders().keySet();
        for (String key : keySet) {
            builder.addHeader(key, request.getRequestHeaders().get(key));
        }

        Request requestNew = builder.build();
        Response response = null;
        try {
            response = httpClient.newCall(requestNew).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, String> h = new HashMap<>();

        for (String name : response.headers().names()) {
            h.put(name, response.header(name));
        }

        String url = request.getUrl().toString();
        String mimeType = getMimeTypeFromUrl(url);

        if (mimeType == null) {
            if (url.contains("js")) {
                mimeType = "application/javascript";
            } else {
                mimeType = "text/html";
            }
        }

        String s = response.body().string();
        InputStream inputStream = new ByteArrayInputStream(s.getBytes());
        WebResourceResponse webResourceResponse = new WebResourceResponse(
                mimeType,
                "utf-8"
                , 200, "ok",
                h,
                inputStream
        );
        return webResourceResponse;
    }

    /**
     * 拦截了webview中的所有请求
     *
     * @param view
     * @param request
     * @return
     */
    @Override
    public final WebResourceResponse shouldInterceptRequest(final WebView view, WebResourceRequest request) {
        if (!request.getUrl().toString().contains("gee")) {
            String requestBody = null;
            Uri uri = request.getUrl();
            // 判断是否为Ajax请求（只要链接中包含AJAXINTERCEPT即是）
            if (request.getMethod().equals("OPTIONS")) {
                return super.shouldInterceptRequest(view, request);
            }
            if (isAjaxRequest(request)) {
                // 获取post请求参数
                requestBody = getRequestBody(request);
                // 获取原链接
                uri = getOriginalRequestUri(request, MARKER);
            }

            WebResourceResponse webResourceResponse = null;
            try {
                webResourceResponse = shouldInterceptRequest(view, new WriteHandlingWebResourceRequest(request, requestBody, uri));
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (webResourceResponse == null) {
                return webResourceResponse;
            } else {
                if (webResourceResponse.getMimeType() == null || request.getMethod().equals("POST")) {
                    return webResourceResponse;
                } else {
                    return injectIntercept(webResourceResponse, view.getContext());
                }
            }
        } else
            return super.shouldInterceptRequest(view, request);
    }


    void addAjaxRequest(String id, String body) {
        ajaxRequestContents.put(id, body);
    }

    /**
     * 获取post请求参数
     *
     * @param request
     * @return
     */
    private String getRequestBody(WebResourceRequest request) {
        String requestID = getAjaxRequestID(request);
        return getAjaxRequestBodyByID(requestID);
    }

    /**
     * 判断是否为Ajax请求
     *
     * @param request
     * @return
     */
    private boolean isAjaxRequest(WebResourceRequest request) {
        return request.getUrl().toString().contains(MARKER);
    }

    private String[] getUrlSegments(WebResourceRequest request, String divider) {
        String urlString = request.getUrl().toString();
        return urlString.split(divider);
    }

    /**
     * 获取请求的id
     *
     * @param request
     * @return
     */
    private String getAjaxRequestID(WebResourceRequest request) {
        return getUrlSegments(request, MARKER)[1];
    }

    /**
     * 获取原链接
     *
     * @param request
     * @param marker
     * @return
     */
    private Uri getOriginalRequestUri(WebResourceRequest request, String marker) {
        String urlString = getUrlSegments(request, marker)[0];
        return Uri.parse(urlString);
    }

    /**
     * 通过请求id获取请求参数
     *
     * @param requestID
     * @return
     */
    private String getAjaxRequestBodyByID(String requestID) {
        String body = ajaxRequestContents.get(requestID);
        ajaxRequestContents.remove(requestID);
        return body;
    }

    /**
     * 如果请求是网页，则html注入
     *
     * @param response
     * @param context
     * @return
     */
    private WebResourceResponse injectIntercept(WebResourceResponse response, Context context) {
        String encoding = response.getEncoding();
        String mime = response.getMimeType();
        // WebResourceResponse的mime必须为"text/html",不能是"text/html; charset=utf-8"
        if (mime.contains("text/html")) {
            mime = "text/html";
        }

        InputStream responseData = response.getData();
        InputStream injectedResponseData = injectInterceptToStream(
                context,
                responseData,
                mime,
                encoding
        );
        return new WebResourceResponse(mime, encoding, injectedResponseData);
    }

    /**
     * 如果请求是网页，则html注入
     *
     * @param context
     * @param is
     * @param mime
     * @param charset
     * @return
     */
    private InputStream injectInterceptToStream(Context context, InputStream is, String mime, String charset) {
        try {
            byte[] pageContents = Utils.consumeInputStream(is);
            if (mime.contains("text/html")) {
                pageContents = AjaxInterceptJavascriptInterface
                        .enableIntercept(context, pageContents)
                        .getBytes(charset);
            }
            return new ByteArrayInputStream(pageContents);

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static String getFileExtensionFromUrl(String url) {
        url = url.toLowerCase();
        if (!TextUtils.isEmpty(url)) {
            int fragment = url.lastIndexOf('#');
            if (fragment > 0) {
                url = url.substring(0, fragment);
            }

            int query = url.lastIndexOf('?');
            if (query > 0) {
                url = url.substring(0, query);
            }

            int filenamePos = url.lastIndexOf('/');
            String filename =
                    0 <= filenamePos ? url.substring(filenamePos + 1) : url;

            // if the filename contains special characters, we don't
            // consider it valid for our matching purposes:
            if (!filename.isEmpty()) {
                int dotPos = filename.lastIndexOf('.');
                if (0 <= dotPos) {
                    return filename.substring(dotPos + 1);
                }
            }
        }
        return "";
    }

    public static String getMimeTypeFromUrl(String url) {
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExtensionFromUrl(url));
    }
}